Skip to content

feat: phase 5 - payments UI, notifications, CSV export, responsive layout#22

Merged
iamvirul merged 13 commits into
masterfrom
feat/phase-5
Jun 18, 2026
Merged

feat: phase 5 - payments UI, notifications, CSV export, responsive layout#22
iamvirul merged 13 commits into
masterfrom
feat/phase-5

Conversation

@iamvirul

@iamvirul iamvirul commented Jun 17, 2026

Copy link
Copy Markdown
Member

Summary

Phase 5 adds customer/supplier payment UIs, an in-app notification bell, CSV export across all Reports tabs, responsive dashboard grid, a lint CI workflow, and resolves all 446 lint warnings.

Type

  • Feature
  • Bug fix
  • Docs
  • Chore

Changes

  • Debtors: tap any debtor to open a detail sheet with outstanding balance, credit limit, full payment history, and "Record Payment" flow (amount, method, notes)
  • Suppliers: payment history section added to supplier detail sheet
  • Notification bell in sidebar (desktop) and floating FAB (mobile) with red badge count; alerts panel covers overdue cheques, due-soon cheques, low-stock products, and credit-limit breaches
  • CSV export on all three Reports tabs (P&L, Stock Valuation, Debtor Aging) shared via system share sheet
  • Dashboard KPI grid reflows to 2/3/4 columns based on viewport width (<480px / <840px / >=840px)
  • New lint.yml CI workflow enforcing zero issues with flutter analyze --fatal-infos --fatal-warnings
  • All 446 lint warnings resolved: package imports, const constructors, deprecated Radio.groupValue/onChanged (migrated to RadioGroup), dynamic calls, positional boolean parameters, type errors
  • MTD card gross profit color changed from mint green to white
  • Settings save button right-aligned; language tile DecoratedBox replaced with Material to fix ink-splash assertion

Screenshots

Test plan

  • Hot reloaded and tested manually
  • Checked on Chrome (flutter run -d chrome)
  • No regressions in related screens
  • flutter analyze reports no issues

Related issues

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a notification bell with an alerts panel (badge + refresh) for overdue/due cheques, low stock, and credit-limit warnings
    • Added debtor detail view with payment history and “Record Payment”
    • Added supplier payment history tracking
    • Added CSV export for P&L, Stock Value, and Debtor Aging reports
    • Enhanced dashboard KPI grid with responsive layout
  • Improvements

    • Updated UI widget const-optimization and refined form initialization
    • Added/strengthened CI lint checks and addressed lint warnings

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 23b7636f-851b-4364-bfb7-531d56430445

📥 Commits

Reviewing files that changed from the base of the PR and between d4eb538 and 395b933.

📒 Files selected for processing (5)
  • lib/core/theme/app_theme.dart
  • lib/features/reports/presentation/reports_screen.dart
  • macos/Runner.xcodeproj/project.pbxproj
  • macos/Runner/Configs/AppInfo.xcconfig
  • windows/runner/Runner.rc
 __________________________________________
< Given enough GPUs, all bugs are shallow. >
 ------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
📝 Walkthrough

Walkthrough

Phase 5 adds debtor detail/payment-recording sheets, supplier payment history, a notification bell aggregating overdue cheques/low-stock/credit alerts, CSV export across all three Reports tabs, and a responsive dashboard KPI grid. Alongside these features, all relative imports are normalized to package:bms/..., 446 lint warnings are resolved, and a GitHub Actions lint CI workflow is introduced.

Changes

Phase 5 Feature Work

Layer / File(s) Summary
Notifications: DAOs, provider, bell widget, and scaffold integration
lib/data/database/daos/cheques_dao.dart, lib/data/database/daos/inventory_dao.dart, lib/data/database/daos/suppliers_dao.dart, lib/providers/notifications_provider.dart, lib/shared/widgets/notification_bell.dart, lib/shared/widgets/app_scaffold.dart, lib/shared/widgets/sidebar_nav.dart
ChequesDao gains getOverdueCheques(), InventoryDao gains getLowStockProducts(), SuppliersDao gains getPaymentsForSupplier(); new AlertType enum, AppAlert class, and notificationsProvider aggregate all four alert sources; NotificationBell renders badge and draggable alerts panel with type-specific icons and refresh handle; integrated as FAB on narrow layouts and in the wide sidebar header.
Debtor detail sheet and payment recording
lib/features/debtors/presentation/debtors_screen.dart
_DebtorTile gains onTap opening _DebtorDetailSheet (DraggableScrollableSheet) with balance, credit limit, and customerPaymentHistoryProvider-driven history; _RecordPaymentSheet adds a validated form recording payments via customerActionsProvider.recordPayment with loading state and snackbars.
Supplier payment history sheet
lib/providers/suppliers_provider.dart, lib/features/suppliers/presentation/suppliers_screen.dart
New supplierPaymentHistoryProvider (FutureProvider.autoDispose.family); _SupplierDetailSheet rewritten as ConsumerWidget inside DraggableScrollableSheet with balanceColor logic, when-driven history rendering, and new _SupplierPaymentRow; payment dropdown changed to initialValue.
Reports CSV export across three tabs
lib/features/reports/presentation/reports_screen.dart
New _shareCsv helper using share_plus/XFile.fromData UTF-8; Export CSV buttons added to P&L (revenue/COGS/gross profit/margin per day), Stock Value (qty/unit cost/total), and Debtor Aging (name/balance/bucket) tabs; P&L date-range end boundary adjusted.
Dashboard responsive KPI grid
lib/features/dashboard/presentation/dashboard_screen.dart
KPI grid replaced from GridView.extent to LayoutBuilder-driven GridView.count computing columns and aspect ratio by width; Gross Profit MTD color changed to white; explicit FlGridData show flags removed; gross-profit barWidth removed; recent invoices wrapper changed from Container to DecoratedBox.
Settings screen structural refactors
lib/features/settings/presentation/settings_screen.dart
Section headers inlined as _SectionHeader; _LanguageTile rewritten using RadioGroup<String> with centralized onChanged; save button wrapped in right-aligned Align; audit log "All" filter changed to const PopupMenuItem without explicit null value; dart:io added for file operations.
Changelog
CHANGELOG.md
[Phase 5] - 2026-06-18 section added documenting all new features, UI changes, and resolved lint warnings.

Lint CI Workflow and Fixes

Layer / File(s) Summary
GitHub Actions lint workflow
.github/workflows/lint.yml
New Lint workflow on push/PR to master and feat/**; installs Flutter 3.44.2, runs build_runner, then flutter analyze --fatal-infos --fatal-warnings with concurrency cancel-in-progress.
Import path normalization
lib/main.dart, lib/app.dart, lib/core/router/..., lib/data/database/..., lib/data/repositories/..., lib/providers/..., lib/features/*/presentation/..., lib/shared/widgets/...
All relative ../... imports converted to package:bms/... across ~60 files; unused flutter_riverpod and dart:typed_data imports removed; import blocks reordered to match analyzer lint order.
Form API migration and flow adjustments
lib/features/cheques/presentation/..., lib/features/customers/presentation/..., lib/features/inventory/presentation/..., lib/features/petty_cash/presentation/..., lib/features/users/presentation/..., lib/features/pos/presentation/..., lib/core/router/...
Changes DropdownButtonFormField value: to initialValue: in 7 screens; removes debugLogDiagnostics; adjusts draggable sheet settings; refactors _buildCorners to named parameters; replaces Container with ColoredBox/DecoratedBox/SizedBox; updates modal result handling logic.
Const, suppressions, and code style cleanup
lib/core/..., lib/data/database/tables/..., lib/features/*/presentation/..., lib/providers/..., lib/shared/widgets/..., tool/preview_receipt.dart
Adds avoid_classes_with_only_static_members and recursive_getters ignore directives; promotes widget constructors to const; removes explicit day parameter from DateTime(year, month, 1)DateTime(year, month); normalizes numeric literals (.0 → integer-style); adjusts fold initializers (0.00); trims PrettyPrinter options; updates PDF decorations to use pw.EdgeInsets.zero; adds cast<Map<String,dynamic>>() in settings JSON import; adds lint ignore comments in tool scripts.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant NotificationBell
  participant notificationsProvider
  participant ChequesDao
  participant InventoryDao
  participant CustomersDao
  participant _AlertsPanel

  User->>NotificationBell: tap bell icon
  NotificationBell->>notificationsProvider: watch (auto-refresh)
  notificationsProvider->>ChequesDao: getOverdueCheques()
  notificationsProvider->>ChequesDao: due within 7 days
  notificationsProvider->>InventoryDao: getLowStockProducts()
  notificationsProvider->>CustomersDao: credit-exceeded customers
  notificationsProvider-->>NotificationBell: List<AppAlert>
  NotificationBell->>_AlertsPanel: showModalBottomSheet
  _AlertsPanel->>_AlertsPanel: render per type (icon + color)
  User->>_AlertsPanel: tap refresh
  _AlertsPanel->>notificationsProvider: invalidate
Loading
sequenceDiagram
  participant User
  participant _DebtorTile
  participant _DebtorDetailSheet
  participant customerPaymentHistoryProvider
  participant _RecordPaymentSheet
  participant customerActionsProvider

  User->>_DebtorTile: tap
  _DebtorTile->>_DebtorDetailSheet: showModalBottomSheet
  _DebtorDetailSheet->>customerPaymentHistoryProvider: watch(customerId)
  customerPaymentHistoryProvider-->>_DebtorDetailSheet: List<Payment>
  User->>_DebtorDetailSheet: tap "Record Payment"
  _DebtorDetailSheet->>_RecordPaymentSheet: Navigator.push
  User->>_RecordPaymentSheet: fill form + submit
  _RecordPaymentSheet->>customerActionsProvider: recordPayment(...)
  customerActionsProvider-->>_RecordPaymentSheet: success
  _RecordPaymentSheet->>_RecordPaymentSheet: Navigator.pop + snackbar
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • getbms/bms#17: Introduced the Reports screen suite that this PR directly extends with CSV export buttons across all three tabs.

Poem

🐇 Hop hop, the lint is gone,
Four hundred warnings — swept at dawn!
A bell now rings for cheques overdue,
Debtors pay, suppliers' history too.
CSV exports zip through the air —
This rabbit ships features with flair! ✨

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/phase-5

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Preview deployed

URL https://getbms.github.io/bms/pr-22/
Commit 0af12e5
Status Live

Updates automatically on every push.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
lib/features/suppliers/presentation/suppliers_screen.dart (1)

130-130: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Potential crash on empty supplier name.

Line 67 in _SupplierTile correctly checks supplier.name.isNotEmpty before accessing supplier.name[0], but this detail sheet does not. If a supplier with an empty name exists, this will throw a RangeError.

🛡️ Proposed fix
               child: Text(
-                  supplier.name[0].toUpperCase(),
+                  supplier.name.isNotEmpty ? supplier.name[0].toUpperCase() : '?',
                   style: const TextStyle(color: Colors.white, fontSize: 22, fontWeight: FontWeight.w700),
               ),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/suppliers/presentation/suppliers_screen.dart` at line 130, The
code at line 130 accesses supplier.name[0] without verifying the supplier name
is not empty, which can cause a RangeError if the supplier has an empty name.
Add a guard condition to check supplier.name.isNotEmpty before accessing
supplier.name[0].toUpperCase(), similar to the pattern already implemented in
the _SupplierTile widget at line 67. If the name is empty, provide a sensible
fallback such as using a default character or returning an empty string for the
display logic.
lib/providers/settings_provider.dart (1)

267-324: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make the JSON import atomic before tightening casts.

The new casts at Lines 272, 288, and 302 can throw after earlier rows were already inserted. Since the catch returns Import failed, wrap the import writes in a Drift transaction so malformed payloads do not leave a partial database restore.

🛡️ Proposed fix
       final payload = jsonDecode(utf8.decode(bytes)) as Map<String, dynamic>;
       final db = _db;
 
-      // Products
-      for (final Map<String, dynamic> p in ((payload['products'] as List?)?.cast<Map<String, dynamic>>() ?? [])) {
-        await db.into(db.products).insert(
-          ProductsCompanion.insert(
-            id: p['id'] as String,
-            name: p['name'] as String,
-            unitType: Value((p['unit_type'] as String?) ?? 'pcs'),
-            costPrice: Value((p['cost_price'] as num?)?.toDouble() ?? 0),
-            sellPrice: Value((p['sell_price'] as num?)?.toDouble() ?? 0),
-            barcode: Value(p['barcode'] as String?),
-            brand: Value(p['brand'] as String?),
-          ),
-          mode: InsertMode.insertOrIgnore,
-        );
-      }
-
-      // Customers
-      for (final Map<String, dynamic> c in ((payload['customers'] as List?)?.cast<Map<String, dynamic>>() ?? [])) {
-        await db.into(db.customers).insert(
-          CustomersCompanion.insert(
-            id: c['id'] as String,
-            name: c['name'] as String,
-            phone: Value(c['phone'] as String?),
-            address: Value(c['address'] as String?),
-            balance: Value((c['balance'] as num?)?.toDouble() ?? 0),
-          ),
-          mode: InsertMode.insertOrIgnore,
-        );
-      }
-
-      // Stock
-      for (final Map<String, dynamic> s in ((payload['stock'] as List?)?.cast<Map<String, dynamic>>() ?? [])) {
-        await db.into(db.stock).insert(
-          StockCompanion.insert(
-            productId: s['product_id'] as String,
-            qty: Value((s['qty'] as num?)?.toDouble() ?? 0),
-          ),
-          mode: InsertMode.insertOrIgnore,
-        );
-      }
-
-      await _ref.read(auditLogDaoProvider).log(
-        id: _uuid.v7(),
-        entityType: 'database',
-        entityId: 'import',
-        action: 'create',
-        userId: _actorId,
-        userName: _actorName,
-        newValue: {'format': 'json', 'source': result.files.first.name},
-      );
+      await db.transaction(() async {
+        // Products
+        for (final Map<String, dynamic> p in ((payload['products'] as List?)?.cast<Map<String, dynamic>>() ?? [])) {
+          await db.into(db.products).insert(
+            ProductsCompanion.insert(
+              id: p['id'] as String,
+              name: p['name'] as String,
+              unitType: Value((p['unit_type'] as String?) ?? 'pcs'),
+              costPrice: Value((p['cost_price'] as num?)?.toDouble() ?? 0),
+              sellPrice: Value((p['sell_price'] as num?)?.toDouble() ?? 0),
+              barcode: Value(p['barcode'] as String?),
+              brand: Value(p['brand'] as String?),
+            ),
+            mode: InsertMode.insertOrIgnore,
+          );
+        }
+
+        // Customers
+        for (final Map<String, dynamic> c in ((payload['customers'] as List?)?.cast<Map<String, dynamic>>() ?? [])) {
+          await db.into(db.customers).insert(
+            CustomersCompanion.insert(
+              id: c['id'] as String,
+              name: c['name'] as String,
+              phone: Value(c['phone'] as String?),
+              address: Value(c['address'] as String?),
+              balance: Value((c['balance'] as num?)?.toDouble() ?? 0),
+            ),
+            mode: InsertMode.insertOrIgnore,
+          );
+        }
+
+        // Stock
+        for (final Map<String, dynamic> s in ((payload['stock'] as List?)?.cast<Map<String, dynamic>>() ?? [])) {
+          await db.into(db.stock).insert(
+            StockCompanion.insert(
+              productId: s['product_id'] as String,
+              qty: Value((s['qty'] as num?)?.toDouble() ?? 0),
+            ),
+            mode: InsertMode.insertOrIgnore,
+          );
+        }
+
+        await _ref.read(auditLogDaoProvider).log(
+          id: _uuid.v7(),
+          entityType: 'database',
+          entityId: 'import',
+          action: 'create',
+          userId: _actorId,
+          userName: _actorName,
+          newValue: {'format': 'json', 'source': result.files.first.name},
+        );
+      });
 
       return 'Import complete';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/providers/settings_provider.dart` around lines 267 - 324, The multiple
insert operations for products, customers, and stock tables are not wrapped in a
database transaction, which means if a cast fails partway through, some inserts
may have already succeeded leaving the database in a corrupted state. Wrap all
the insert operations (the three for loops iterating over products, customers,
and stock, as well as the audit log call) inside a Drift transaction to ensure
atomicity. This way, if any error occurs during the import process, the entire
transaction will be rolled back and the database will remain in a consistent
state.
lib/features/settings/presentation/settings_screen.dart (1)

476-485: ⚠️ Potential issue | 🟠 Major

Use a non-null sentinel for the "All" audit filter option.

Selecting the "All" item (line 484) with no value specified results in null being returned. In Flutter's PopupMenuButton, null is treated as menu cancellation, so onSelected is never invoked. This leaves _filterType stuck on the previous selection instead of clearing the filter. Use a non-null sentinel value like '__all__' and map it back to null in the onSelected handler.

Proposed fix
-          PopupMenuButton<String?>(
+          PopupMenuButton<String>(
             icon: Badge(
               isLabelVisible: _filterType != null,
               child: const Icon(Icons.filter_list),
             ),
             tooltip: 'Filter by type',
-            onSelected: (v) => setState(() => _filterType = v),
+            onSelected: (v) => setState(() => _filterType = v == '__all__' ? null : v),
             itemBuilder: (_) => [
-              const PopupMenuItem(child: Text('All')),
+              const PopupMenuItem(value: '__all__', child: Text('All')),
               ..._types.map((t) => PopupMenuItem(value: t, child: Text(t))),
             ],
           ),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/settings/presentation/settings_screen.dart` around lines 476 -
485, The "All" PopupMenuItem on line 484 has no value specified, which returns
null and causes PopupMenuButton to treat it as a menu cancellation rather than a
valid selection, preventing onSelected from being invoked and leaving
_filterType unchanged. Assign a non-null sentinel value like '__all__' to the
"All" PopupMenuItem, then modify the onSelected callback in the PopupMenuButton
to check if the selected value equals '__all__' and map it to null when setting
_filterType, ensuring the callback executes and the filter is properly cleared.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 9-28: The Phase 5 section header includes a future date
(2026-06-18) that makes the unreleased version appear as if it's already been
released, which will cause confusion and drift if the release date changes.
Remove the date from the Phase 5 heading so it reads as either an undated phase
heading or change it to use the Unreleased designation, keeping only the version
information without the specific date until the release is finalized.

In `@lib/features/debtors/presentation/debtors_screen.dart`:
- Around line 219-225: The avatar section's Text widget directly accesses
customer.name[0] without checking if the name is empty, which will throw a
RangeError for customers with empty names. Add a guard condition in the Text
child to check if customer.name is not empty before accessing the first
character, and provide a fallback character (such as '?') when the name is
empty, matching the defensive pattern already implemented in _DebtorTile at line
155. This ensures consistency across the debtors_screen.dart file and prevents
runtime crashes.

In `@lib/features/pos/presentation/receipt_pdf.dart`:
- Around line 1-7: The receipt_pdf.dart file uses Uint8List.fromList(...) on
lines 49 and 52 but is missing the required import for Uint8List. Add the import
statement `import 'dart:typed_data';` to the import section at the top of the
file alongside the other existing imports, as Uint8List is not available through
any of the current imports including package:flutter/services.dart.

In `@lib/features/reports/presentation/reports_screen.dart`:
- Around line 186-199: The onPressed callback that calls _shareCsv() does not
handle potential failures from the share operation, leaving users without
feedback if something goes wrong. Make the onPressed callback an async function,
await the _shareCsv() call, and wrap it in a try-catch block. In the catch
block, display an error message to the user via a SnackBar or dialog to inform
them that the export failed. Apply this same pattern to all three export button
handlers mentioned in the comment.
- Around line 375-376: Create a utility function to properly escape CSV fields
by wrapping values in double quotes and escaping any internal quotes by doubling
them, and also strip or escape leading special characters (equals, plus, minus,
at-sign) that could trigger formula injection. Apply this sanitization function
to the r.name field in the map operation used for CSV export at the location
containing rows.map, and also apply the same function to any other
user-controlled field being interpolated into the CSV string at the second
occurrence around line 598-600. Ensure all string interpolations that include
user-provided data are passed through this sanitization function before being
added to the CSV output.
- Around line 98-99: The end date calculation in the date range for the report
(line 99) subtracts only 1 second from the next-month midnight, which excludes
records in the final milliseconds of the last day. Replace the Duration(seconds:
1) subtraction with Duration(milliseconds: 1) to capture the full end-of-day
precision and ensure all valid sales records are included when filtering with
isBetweenValues for both the P&L report and exported CSV data.

In `@lib/features/settings/presentation/settings_screen.dart`:
- Around line 1-13: The unconditional `import 'dart:io';` statement at the top
of settings_screen.dart causes compilation failures for Flutter web builds
because Dart's static compiler analysis rejects dart:io imports for web targets,
even though the File usage is guarded by kIsWeb at runtime in _downloadBytes.
Replace the static `import 'dart:io';` with a conditional import using `import
'dart:io' if (dart.library.html) 'dart:html';` to handle both IO and web
platforms, or extract the file download logic that depends on dart:io into a
separate platform-specific helper file and conditionally import the appropriate
implementation based on the target platform.

---

Outside diff comments:
In `@lib/features/settings/presentation/settings_screen.dart`:
- Around line 476-485: The "All" PopupMenuItem on line 484 has no value
specified, which returns null and causes PopupMenuButton to treat it as a menu
cancellation rather than a valid selection, preventing onSelected from being
invoked and leaving _filterType unchanged. Assign a non-null sentinel value like
'__all__' to the "All" PopupMenuItem, then modify the onSelected callback in the
PopupMenuButton to check if the selected value equals '__all__' and map it to
null when setting _filterType, ensuring the callback executes and the filter is
properly cleared.

In `@lib/features/suppliers/presentation/suppliers_screen.dart`:
- Line 130: The code at line 130 accesses supplier.name[0] without verifying the
supplier name is not empty, which can cause a RangeError if the supplier has an
empty name. Add a guard condition to check supplier.name.isNotEmpty before
accessing supplier.name[0].toUpperCase(), similar to the pattern already
implemented in the _SupplierTile widget at line 67. If the name is empty,
provide a sensible fallback such as using a default character or returning an
empty string for the display logic.

In `@lib/providers/settings_provider.dart`:
- Around line 267-324: The multiple insert operations for products, customers,
and stock tables are not wrapped in a database transaction, which means if a
cast fails partway through, some inserts may have already succeeded leaving the
database in a corrupted state. Wrap all the insert operations (the three for
loops iterating over products, customers, and stock, as well as the audit log
call) inside a Drift transaction to ensure atomicity. This way, if any error
occurs during the import process, the entire transaction will be rolled back and
the database will remain in a consistent state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9839ac7b-d55e-4452-8410-d01e747163b4

📥 Commits

Reviewing files that changed from the base of the PR and between 06f307f and 0b399ef.

📒 Files selected for processing (69)
  • .github/workflows/lint.yml
  • CHANGELOG.md
  • lib/app.dart
  • lib/core/constants/app_constants.dart
  • lib/core/router/app_router.dart
  • lib/core/router/route_guard.dart
  • lib/core/theme/app_text_styles.dart
  • lib/core/theme/app_theme.dart
  • lib/core/utils/currency_utils.dart
  • lib/core/utils/date_utils.dart
  • lib/core/utils/logger.dart
  • lib/data/database/app_database.dart
  • lib/data/database/daos/audit_log_dao.dart
  • lib/data/database/daos/cheques_dao.dart
  • lib/data/database/daos/customers_dao.dart
  • lib/data/database/daos/inventory_dao.dart
  • lib/data/database/daos/invoices_dao.dart
  • lib/data/database/daos/petty_cash_dao.dart
  • lib/data/database/daos/reports_dao.dart
  • lib/data/database/daos/returns_dao.dart
  • lib/data/database/daos/suppliers_dao.dart
  • lib/data/database/daos/users_dao.dart
  • lib/data/database/tables/products_table.dart
  • lib/data/database/tables/returns_table.dart
  • lib/data/repositories/auth_repository.dart
  • lib/data/repositories/inventory_repository.dart
  • lib/features/auth/domain/auth_state.dart
  • lib/features/auth/presentation/login_screen.dart
  • lib/features/cheques/presentation/cheque_screen.dart
  • lib/features/customers/presentation/customers_screen.dart
  • lib/features/dashboard/presentation/dashboard_screen.dart
  • lib/features/debtors/presentation/debtors_screen.dart
  • lib/features/grn/presentation/grn_screen.dart
  • lib/features/inventory/presentation/inventory_screen.dart
  • lib/features/invoices/presentation/invoice_detail_screen.dart
  • lib/features/invoices/presentation/invoice_pdf.dart
  • lib/features/invoices/presentation/invoices_screen.dart
  • lib/features/petty_cash/presentation/petty_cash_screen.dart
  • lib/features/pos/presentation/pos_screen.dart
  • lib/features/pos/presentation/receipt_pdf.dart
  • lib/features/quick_sales/presentation/quick_sales_screen.dart
  • lib/features/reports/presentation/reports_screen.dart
  • lib/features/settings/presentation/settings_screen.dart
  • lib/features/suppliers/presentation/suppliers_screen.dart
  • lib/features/users/presentation/users_screen.dart
  • lib/main.dart
  • lib/providers/auth_provider.dart
  • lib/providers/cheques_provider.dart
  • lib/providers/customers_provider.dart
  • lib/providers/dashboard_provider.dart
  • lib/providers/database_provider.dart
  • lib/providers/grn_provider.dart
  • lib/providers/inventory_provider.dart
  • lib/providers/invoices_provider.dart
  • lib/providers/notifications_provider.dart
  • lib/providers/petty_cash_provider.dart
  • lib/providers/pos_provider.dart
  • lib/providers/quick_sale_provider.dart
  • lib/providers/settings_provider.dart
  • lib/providers/suppliers_provider.dart
  • lib/providers/users_provider.dart
  • lib/shared/widgets/app_scaffold.dart
  • lib/shared/widgets/bms_error_widget.dart
  • lib/shared/widgets/bms_filter_bar.dart
  • lib/shared/widgets/confirmation_dialog.dart
  • lib/shared/widgets/notification_bell.dart
  • lib/shared/widgets/sidebar_nav.dart
  • lib/shared/widgets/stat_card.dart
  • tool/preview_receipt.dart
💤 Files with no reviewable changes (1)
  • lib/core/utils/logger.dart

Comment thread CHANGELOG.md Outdated
Comment thread lib/features/debtors/presentation/debtors_screen.dart
Comment thread lib/features/pos/presentation/receipt_pdf.dart
Comment thread lib/features/reports/presentation/reports_screen.dart Outdated
Comment thread lib/features/reports/presentation/reports_screen.dart Outdated
Comment thread lib/features/reports/presentation/reports_screen.dart Outdated
Comment thread lib/features/settings/presentation/settings_screen.dart
iamvirul and others added 2 commits June 18, 2026 00:35
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@hiranyasemindi

Copy link
Copy Markdown
Collaborator

@iamvirul pls check the coderabbit reviews

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@iamvirul iamvirul merged commit a5df1ca into master Jun 18, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants